﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Threading;
using KouSuan.Models;
using System.Timers;
using System.Speech.Recognition;
using System.Windows;
using GalaSoft.MvvmLight.Messaging;
using KouSuan.Classes;


namespace KouSuan.ViewModels
{
    public class GameViewModel : ViewModelBase
    {
        #region fields

        /// <summary>
        /// 答题计时器
        /// </summary>
        private Timer _timer;
        /// <summary>
        /// 答题时使用的识别引擎
        /// </summary>
        private SpeechRecognitionEngine _answerEngine;
        /// <summary>
        /// 控制开始停止的识别引擎
        /// </summary>
        private SpeechRecognitionEngine _cmdEngine;
        /// <summary>
        /// 得出算式的随机类
        /// </summary>
        private Random _random;

        #endregion fields

        public GameViewModel()
        {
            if (!IsInDesignMode)
            {
                this.InitializeRandom();
                this.InitializeTimer();
                this.InitializeCmdEngine();
            }
        }

        #region 私有方法

        /// <summary>
        /// 初始化随机数处理器
        /// </summary>
        private void InitializeRandom()
        {
            this._random = new Random();
        }

        /// <summary>
        /// 初始化计时器
        /// </summary>
        private void InitializeTimer()
        {
            this._timer = new Timer(1000);
            this._timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
        }

        void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                if (this.NowProcess > 0)
                {
                    this.NowProcess -= 1;
                }
                else
                {
                    // 提示错误，重新开始下一题
                    this._timer.Stop();

                    // 提示错误
                    this.IsRight = false;

                    // 发消息显示错误信息
                    NotificationMessageWithCallback nw = new NotificationMessageWithCallback(this,
                                                            "错误",
                                                            new Action(() =>
                                                            {
                                                                this.StartNewExpression();
                                                            }));
                    Messenger.Default.Send<NotificationMessageWithCallback>(nw, MessageTokens.ShowResultCartoon);
                }
            });
        }

        /// <summary>
        /// 初始化答题
        /// </summary>
        private void InitializeAnswerEngine()
        {
            this._answerEngine = new SpeechRecognitionEngine(System.Globalization.CultureInfo.CurrentCulture);
            this._answerEngine.LoadGrammar(GetNewGrammar("一"));
            this._answerEngine.SetInputToDefaultAudioDevice();
            this._answerEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(_answerEngine_SpeechRecognized);
            this._answerEngine.RecognizeAsync(RecognizeMode.Multiple);
        }

        void _answerEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            string text = e.Result.Text;
            // 判断答案是否正确
            CheckAnswer(text);
        }

        /// <summary>
        /// 判断答案是否正确
        /// </summary>
        /// <param name="text"></param>
        private void CheckAnswer(string text)
        {
            NotificationMessageWithCallback nw = null;
            if (text.Trim() == this.Expression.Answer.ToString())
            {
                // 设置为正确
                this.IsRight = true;
                // 暂停计时
                this._timer.Stop();
                // 设置要发送的消息
                nw = new NotificationMessageWithCallback(this,
                                                        "正确",
                                                        new Action(() =>
                                                        {
                                                            this.StartNewExpression();
                                                        }));

            }
            else
            {
                // 提示错误
                this.IsRight = false;

                nw = new NotificationMessageWithCallback(this,
                                                        "错误",
                                                        new Action(() =>
                                                        {
                                                            //this.StartNewExpression();
                                                        }));
            }
            Messenger.Default.Send<NotificationMessageWithCallback>(nw, MessageTokens.ShowResultCartoon);
        }

        private void InitializeCmdEngine()
        {
            _cmdEngine = new SpeechRecognitionEngine(System.Globalization.CultureInfo.CurrentCulture);
            Grammar g = GetNewGrammar(new string[] { "开始", "停止" });
            _cmdEngine.LoadGrammar(g);
            _cmdEngine.SetInputToDefaultAudioDevice();
            _cmdEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(_cmdEngine_SpeechRecognized);
            _cmdEngine.RecognizeAsync(RecognizeMode.Multiple);
        }

        void _cmdEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            string text = e.Result.Text;
            if (text == "开始")
            {
                if (this._answerEngine == null)
                {
                    this.InitializeAnswerEngine();
                }

                StartNewExpression();
            }
            else if (text == "停止")
            {

            }
        }

        /// <summary>
        /// 开始新的一题
        /// </summary>
        private void StartNewExpression()
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                // 将提示状态设置为默认
                this.IsRight = null;
                // 获取新的一题               
                this.Expression = GetNewExpression();
                // 设置识别词                
                ResetAnswerEngine();
                // 重置进度值
                this.NowProcess = this.Maximum;
                // 重新开始计时
                this._timer.Start();
            });
        }

        /// <summary>
        /// 重新设置答题语音识别引起的识别词
        /// </summary>
        private void ResetAnswerEngine()
        {
            Grammar g = GetNewGrammar(this.Expression.Answer.ToString());
            this._answerEngine.UnloadAllGrammars();
            this._answerEngine.LoadGrammar(g);
        }

        /// <summary>
        /// 获取一个新的语法
        /// </summary>
        /// <param name="words">识别词</param>
        /// <returns></returns>
        private Grammar GetNewGrammar(params string[] words)
        {
            Choices choices = new Choices(words);
            GrammarBuilder gb = new GrammarBuilder(choices);
            Grammar g = new Grammar(gb);
            return g;
        }

        /// <summary>
        /// 获取随机产生的计算表达式
        /// </summary>
        /// <returns></returns>
        private ExpressionModel GetNewExpression()
        {
            ExpressionModel expression = new ExpressionModel();

            // 取计算符号
            int opIndex = this._random.Next(0, this._opraters.Length);
            char op = this._opraters[opIndex];
            expression.Oprator = op;

            int max = this.MaxSumNum + 1;
            int left = this._random.Next(0, max);
            expression.LeftNum = left;

            int rightMax = 0;
            switch (op)
            {
                case '+':
                    rightMax = max - left;
                    break;
                case '-':
                    rightMax = left;
                    break;
                case '×':
                    rightMax = max / left;
                    break;
                case '÷':
                    rightMax = left;
                    break;
                default:
                    break;
            }
            int right = this._random.Next(0, rightMax);
            expression.RightNum = right;

            return expression;
        }

        #endregion 私有方法

        #region properties

        /// <summary>
        /// 算式类型 + - × ÷
        /// </summary>
        private char[] _opraters = new char[] { '+', '-' };
        /// <summary>
        /// 算式类型 + - × ÷
        /// </summary>
        public char[] Opraters
        {
            get { return _opraters; }
            set
            {
                if (value != _opraters)
                {
                    _opraters = value;
                    RaisePropertyChanged(() => Opraters);
                }
            }
        }

        private int _MaxSumNum = 20;
        /// <summary>
        /// 算式范围，比如20以内则此处设为20，默认为20
        /// </summary>
        public int MaxSumNum
        {
            get { return _MaxSumNum; }
            set
            {
                if (value != _MaxSumNum)
                {
                    _MaxSumNum = value;
                    RaisePropertyChanged(() => Maximum);
                }
            }
        }

        /// <summary>
        /// 最大进度值
        /// </summary>
        public int Maximum
        {
            get
            {
                return 60;
            }
        }

        private int _NowProcess = 60;
        /// <summary>
        /// 当前的时间进度
        /// </summary>
        public int NowProcess
        {
            get { return _NowProcess; }
            set
            {
                if (value != _NowProcess)
                {
                    _NowProcess = value;
                    RaisePropertyChanged(() => NowProcess);
                }
            }
        }

        private ExpressionModel _Expression;
        /// <summary>
        /// 算式
        /// </summary>
        public ExpressionModel Expression
        {
            get { return _Expression; }
            set
            {
                if (value != _Expression)
                {
                    _Expression = value;
                    RaisePropertyChanged(() => Expression);
                }
            }
        }

        private bool? _IsRight;
        /// <summary>
        /// 当前的答案是否正确
        /// </summary>
        public bool? IsRight
        {
            get { return _IsRight; }
            set
            {
                if (value != null)
                {
                    _IsRight = value;
                    RaisePropertyChanged(() => IsRight);
                }
            }
        }


        #endregion properties
    }
}
